package nl.tue.be.ds.duraark.bSDD.dump.alternatives;

import java.util.HashMap;
import java.util.Iterator;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import javax.ws.rs.core.MediaType;

import nl.tue.be.ds.duraark.bSDD.ClientUtilities;
import nl.tue.be.ds.duraark.bSDD.DataBaseStorageUnit;
import nl.tue.be.ds.duraark.bSDD.DataBaseUtilities;
import nl.tue.be.ds.duraark.bSDD.dump.RelSearchPerGuidCallable;

import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.UniformInterfaceException;
import com.sun.jersey.api.client.WebResource;

public class ConInRelSearchPerGuid {
	
	private String searchGuid;
	private final String searchByGuidUrl = "http://bsddpilot.catenda.no/api/4.0/IfdConcept/";

	public ConInRelSearchPerGuid(String searchGuid) {
		this.searchGuid = searchGuid;
	}
	
	public Integer dumpPerGuid(JsonNode jsonConcepts){
		Integer i = 0;
		
		/*DumpStorageUnitCallable dsu = new DumpStorageUnitCallable(jsonConcepts);		
		ExecutorService threadPool = Executors.newSingleThreadExecutor();
		Future<Integer> f = threadPool.submit(dsu);
		System.out.println("xxxxxxxxx dumpPerGuid function  before get");
		try {
				i = f.get();
		} catch (InterruptedException e) {
			
			e.printStackTrace();
		} catch (ExecutionException e) {
			
			e.printStackTrace();
		}
		System.out.println("yyyyyyyyyyyyy dumpPerGuid function after get");
		threadPool.shutdown();
		try {
			threadPool.awaitTermination(60, TimeUnit.SECONDS);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}*/
		
		
		i = dumpSearchedConcepts(jsonConcepts);
		
		
		return i;
		
	}
	
	
	public JsonNode searchPerGuid() throws Exception{
		String res = null;
		JsonNode jsonConcepts;
	
		
		res = getSearch();
	
		System.out.println("pass search, res : "+res);
		
		if (res != null) {
			ObjectMapper mapper = ClientUtilities.getMapper();
			jsonConcepts = mapper.readTree(res);	
		} else {
			jsonConcepts = null;
		}
		return jsonConcepts;
		
	}
	
	private String getSearch() throws InterruptedException{
		String res = null;
		
		Client client = ClientUtilities.getClient();

		WebResource searchCall = client.resource(searchByGuidUrl + searchGuid);
		
		try{
			res = searchCall.accept(MediaType.APPLICATION_JSON_TYPE).cookie(ClientUtilities.cookie).get(String.class);
		}catch(Exception e){
			if (e instanceof UniformInterfaceException){
				//Thread.sleep(1000);
				res = getSearch();
			}else{
				e.printStackTrace();
			}	
		}		
		return res;	
	}
	
	
	private int dumpSearchedConcepts(JsonNode jsonConcepts) {
		int conceptCounter = 0;
		
		if (jsonConcepts != null) {

			if (jsonConcepts.isArray()) {
				Iterator<JsonNode> it = jsonConcepts.iterator();
				while (it.hasNext()) {
					JsonNode jsonNode = it.next();
					boolean b = DataBaseUtilities.isConceptExistedInDB(jsonNode, DataBaseUtilities.db);
					if(!b){
						
						DataBaseStorageUnit dumpStorageUnit = getDumpStorageUnit(jsonNode);
						
						System.out.println("Concept with this Guid just be dumped : "+ dumpStorageUnit.getGuid());
						
						/*if (dumpStorageUnit.getParentsGuidMap()== null)
							System.out.println("No parents rels");
						else{
							Iterator<String> iter = dumpStorageUnit.getParentsGuidMap().keySet().iterator();
							while(iter.hasNext()){
								String conceptGuid = (String) iter.next();
								System.out.println("Parents rels: "+ conceptGuid + "<---->" + dumpStorageUnit.getParentsGuidMap().get(conceptGuid));
							}
						}
						if (dumpStorageUnit.getChildrenGuidMap()== null)
							System.out.println("No children rels");
						else
						{
							Iterator<String> iter = dumpStorageUnit.getChildrenGuidMap().keySet().iterator();
							while(iter.hasNext()){
								String conceptGuid = (String) iter.next();
								System.out.println("Children rels: "+ conceptGuid + "<---->" + dumpStorageUnit.getChildrenGuidMap().get(conceptGuid));
							}
						}*/
								
						DataBaseUtilities.db.store(dumpStorageUnit);
						conceptCounter++;
						}
					}
			} else {
				boolean b = DataBaseUtilities.isConceptExistedInDB(jsonConcepts,DataBaseUtilities.db);
				if(!b){
					
					DataBaseStorageUnit dumpStorageUnit = getDumpStorageUnit(jsonConcepts);
					
					System.out.println("Concept with this Guid just be dumped : " + dumpStorageUnit.getGuid());
					
					/*if (dumpStorageUnit.getParentsGuidMap()== null)
						System.out.println("No parents rels");
					else{
						Iterator<String> iter = dumpStorageUnit.getParentsGuidMap().keySet().iterator();
						while(iter.hasNext()){
							String conceptGuid = (String) iter.next();
							System.out.println("Parents rels: "+ conceptGuid + "<---->" + dumpStorageUnit.getParentsGuidMap().get(conceptGuid));
						}
					}
					if (dumpStorageUnit.getChildrenGuidMap()== null)
						System.out.println("No children rels");
					else
					{
						Iterator<String> iter = dumpStorageUnit.getChildrenGuidMap().keySet().iterator();
						while(iter.hasNext()){
							String conceptGuid = (String) iter.next();
							System.out.println("Children rels: "+ conceptGuid + "<---->" + dumpStorageUnit.getChildrenGuidMap().get(conceptGuid));
						}
					}*/
					
					DataBaseUtilities.db.store(dumpStorageUnit);
					conceptCounter++;
					
				}
			}	
				
		}
		return conceptCounter;
	}
	
	private DataBaseStorageUnit getDumpStorageUnit(JsonNode jsonNode) {
		
		DataBaseStorageUnit dumpStorageUnit = new DataBaseStorageUnit() ;
		
		String guid = jsonNode.get("guid").getTextValue();
		dumpStorageUnit.setGuid(guid);
		dumpStorageUnit.setConceptJN(jsonNode);
		setParentsRels(guid, dumpStorageUnit);
		setChildrenRels(guid, dumpStorageUnit);
		
		return dumpStorageUnit;
	}
	
	
	private void setParentsRels(String guid, DataBaseStorageUnit dumpStorageUnit){
		
		RelSearchPerGuidCallable parentsCrc = new RelSearchPerGuidCallable(guid, "parents");
		//ConceptRelFloodingCallable parentsCrc = new ConceptRelFloodingCallable(guid, "parents");
		ExecutorService threadPool = Executors.newSingleThreadExecutor();
		Future<HashMap<String, String>> parentsf = threadPool.submit(parentsCrc);
		
		HashMap<String, String> relsMap = getRels(parentsf, 0);	
		dumpStorageUnit.setParentsGuidMap(relsMap);
		
		threadPool.shutdown();
		
		//System.out.println("PPPPPP  Parents pool down? " + threadPool.isShutdown() + " terminated? " + threadPool.isTerminated());
		 
	}
	
	private void setChildrenRels(String guid, DataBaseStorageUnit dumpStorageUnit){
		
		RelSearchPerGuidCallable childrenCrc = new RelSearchPerGuidCallable(guid, "children");
		//ConceptRelFloodingCallable childrenCrc = new ConceptRelFloodingCallable(guid, "children");
		ExecutorService threadPool = Executors.newSingleThreadExecutor();
		Future<HashMap<String, String>> childrenf = threadPool.submit(childrenCrc);
		
		HashMap<String, String> relsMap = getRels(childrenf, 0);	
		dumpStorageUnit.setChildrenGuidMap(relsMap);
		
		threadPool.shutdown();
		
		//System.out.println("CCCCCC Children pool down? " + threadPool.isShutdown() + " terminated? " + threadPool.isTerminated());
		
	}
	
	
	private HashMap<String, String> getRels(Future<HashMap<String, String>> future, int recDep){
		HashMap<String, String> relsMap = new HashMap<String, String>();
		
		if (recDep < 20) {
			try {
				relsMap = future.get();
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (ExecutionException e) {
				getRels(future, recDep + 1);
			}
		} /*else {
			relsMap.put(DataBaseUtilities.stringGuidForRelOverflow, DataBaseUtilities.stringGuidForRelOverflow);
		}*/
		return relsMap;
		
	}
	
	
}
